<script setup lang="ts">
// 组件内定义事件用小写，hooks引入用大写
import TableOperation from '@/components/TableOperation.vue'
import MultipleOperation from '@/components/MultipleOperation.vue'
import DialogRowView from './DialogRowView.vue'
import DialogRowAddEdit from './DialogRowAddEdit.vue'
import $mitt from '@/common/emitter'
import { 
	INJECT_SYS_NAME, 
	INJECT_SWITCH_ON_COLOR, 
	INJECT_SWITCH_OFF_COLOR,
	INJECT_REQUEST_SUCCESS_NO 
} from '@/common/provideType'
import { 
	serviceListRqs, 
	serviceListDetailsRqs, 
	serviceListDetailsAddRqs, 
	serviceListDetailsEditRqs,
	serviceListDetailsDeleteRqs,
	serviceSwitchOnRqs, 
	serviceSwitchOffRqs
} from '@/request/api'
import { 
	tableDataInit, 
	TABLE_DATA_SELECT_EVENT_FN, 
	SWITCH_BEFORE_CHANGE_FN, 
} from '@/common/hooks'

import type { Events } from '@/common/emitter'
import type { SwitchUpdateFnParamsType, ResponseType } from '@/request/apiType'
import type { TableHeaderColumnsItemType, TableDataInitType } from '@/components/tableType'
import type { DialogConfigType } from '@/components/dialogType'
import { INJECT_THEME_COLOR } from '@/common/provideType'

const SYS_NAME = inject(INJECT_SYS_NAME)!
const REQUEST_SUCCESS_NO = inject(INJECT_REQUEST_SUCCESS_NO)
const THEME_COLOR = inject(INJECT_THEME_COLOR)
const SWITCH_ON_COLOR = inject(INJECT_SWITCH_ON_COLOR)
const SWITCH_OFF_COLOR = inject(INJECT_SWITCH_OFF_COLOR)
const vPreventReClick = inject('vPreventReClick')
const vAuth = inject('vAuth')
const DIALOG_TYPE_VIEW = 'view'
const DIALOG_TYPE_ADD = 'add'
const DIALOG_TYPE_EDIT = 'edit'
const dialogRowViewRef = ref<InstanceType<typeof DialogRowView>>()
const dialogAddEditRef = ref<InstanceType<typeof DialogRowAddEdit>>()
const tableRef = ref<InstanceType<typeof TableOperation>>()

// 表格头
const tableHeaderColumns: TableHeaderColumnsItemType[] = reactive([
	{label: '实例ID', prop: 'id'},
	{label: '实例名称', prop: 'name'} ,
	{label: '是否启用', prop: 'is_enable', isSlot: true, slotName: 'switchSlot', align: 'center'},
	{label: '版本', prop: 'version', align: 'center'},
	{label: '内部版本', prop: 'build_info', align: 'center'},
	{label: '部署类型', prop: 'deploy_type', isSlot: true, slotName: 'deployTypeSlot', align: 'center'},
	{label: '主/备', prop: 'is_primary', width: 60, align: 'center', isSlot: true, slotName: 'primarySlot'},
	{label: '监听端口', prop: 'listen_addr'},
	{label: 'Nat地址', prop: 'nat_addr'},
	{label: '权重', prop: 'weight', align: 'center'},
	{label: '管理端口', prop: 'listen_addr_admin'},
	{label: '创建时间', prop: 'start_timeStamp'}
])
// 表格内容
const tableData: TableDataInitType = reactive({
	...tableDataInit,
	isReplaceSpaceFlag: true,
	lineHeightFlag: true,
	tableMaxHeight: 600,
	operationConfig: {
		isShowFlag: true
	},
	isPreviewFlag: true,
	isEditFlag: true,
	isDeleteFlag: true,
	isMultipleOperationFlag: true
})

type RowType = typeof tableData.value.data[0]
type RowsType = RowType[]
type ServiceListType = {
	service_name: string
	deploy_type: number
	[property: string]: any
}
type MainParamsType = {
	serviceList: ServiceListType[]
	[property: string]: any
}
const mainParams: MainParamsType = reactive({
	serviceIndex: -1,
	serviceName: '',
	serviceList: [],

	// 批量操作配置
	multipleConfig: [
		tableDataInit.multipleDelete, 
		tableDataInit.multipleSwitchOn, 
		tableDataInit.multipleSwitchOff
	]
})

// 请求服务列表
const queryServiceListFn = async () => {
	// 模拟返回结果
	const params = {sys_name: SYS_NAME}
	let res = await serviceListRqs(params)
	if(res?.code === REQUEST_SUCCESS_NO) {
		mainParams.serviceList = res.data!
		mainParams.serviceList.forEach(item => {
			switch (item.deploy_type) {
				case 1:
					item.bgColor = 'success'
					break
				case 2:
					item.bgColor = 'warning'
					break
				case 3:
					item.bgColor = 'danger'
					break
			}
			item.currentPage = 1
			item.pageSize = 10
		})

		// 初始化第一个服务实例列表
		mainParams.serviceList?.length  && queryServiceListDetailFn(0)
	} 
}

// 请求服务实例
const queryServiceListDetailFn = async (index: number) => {
	const serviceItem = mainParams.serviceList[index]
	mainParams.serviceName = serviceItem.service_name
	mainParams.serviceIndex = index
	
	let res = await serviceListDetailsRqs({
		sys_name: SYS_NAME,
		service_name: mainParams.serviceName,
		page_no: serviceItem.currentPage || tableData.currentPage,
		page_size: serviceItem.pageSize || tableData.pageSize
	})
	
	if(res && res.code === REQUEST_SUCCESS_NO) {
		tableData.data = res.data!
		tableData.total = res.total!

		// 当前服务实例对应的分页数据
		tableData.currentPage = serviceItem.currentPage || tableData.currentPage
		tableData.pageSize = serviceItem.pageSize || tableData.pageSize
	} 
}

// dialogType = view, add, edit, othres
const dialogConfig: DialogConfigType  = reactive({
	dialogVisible: false,
	dialogType: '',
	title: '',
	width: 0,
	row: {},
	dialoFootFlag: true
})

// 预览/新增/编辑弹窗设置
const setDialogConfigFn = (dialogConfigFnParams: DialogConfigType ) => {
	Object.assign(dialogConfig, dialogConfigFnParams)
	const dialogTarget = dialogConfig.dialogTarget
	if(dialogConfig.dialogType === DIALOG_TYPE_VIEW) dialogTarget.exposeOpenDialogViewFn(dialogConfig)
	else if(dialogConfig.dialogType === DIALOG_TYPE_ADD || dialogConfig.dialogType === DIALOG_TYPE_EDIT) dialogTarget.exposeOpenDialogAdd_EditFn(dialogConfig)
	else dialogTarget.exposeOpenDialogOthersFn(dialogConfig)
}

// 预览
const tableDataViewEventFn = (row: RowType): void => setDialogConfigFn({
	dialogVisible: true, 
	dialogType: DIALOG_TYPE_VIEW, 
	dialogTarget: dialogRowViewRef.value,
	title: '预览', 
	width: 800,
	row,
	dialoFootFlag: false
})

// 新增
const tableDataAddEventFn = (): void  => setDialogConfigFn({
	dialogVisible: true, 
	dialogType: DIALOG_TYPE_ADD, 
	dialogTarget: dialogAddEditRef,
	title: '新增服务实例', 
	width: 800,
	row: {},
	dialoFootFlag: true
})

// 编辑
const tableDataEditEventFn = (row: RowType): void => setDialogConfigFn({
	dialogVisible: true, 
	dialogType: DIALOG_TYPE_EDIT, 
	dialogTarget: dialogAddEditRef,
	title: '服务实例编辑', 
	width: 800,
	row,
	dialoFootFlag: true
})

// 新增/编辑 确认
const confirmSubmitEventFn = async (row: RowType) => {
	// 调用接口，提交数据
	let res: ResponseType = {code: -1, msg: '', data: [], total: -1} 
	const params = {
		sys_name: SYS_NAME,
		service_name: mainParams.serviceName,
		...row
	}
	if(dialogConfig.dialogType === DIALOG_TYPE_ADD) res = await serviceListDetailsAddRqs(params)
	if(dialogConfig.dialogType === DIALOG_TYPE_EDIT) {
		delete params.is_enable
		res = await serviceListDetailsEditRqs(params)
	}
	if(res?.code === REQUEST_SUCCESS_NO) {
		ElMessage.success(res.msg)
	} else {
		ElMessage.error(res.msg)
	}
	// 更新页面数据
	queryServiceListDetailFn(mainParams.serviceIndex)
	dialogAddEditRef.value?.exposeCloseDialogAdd_EditFn()
}

// 删除/批量删除，从表格组件 TableOperation.vue 过来
const tableDataDeleteEventFn = (rows: RowType, isMultipleDeletetFlag: boolean = false): void => {
	ElMessageBox.confirm(
		'数据将被永久删除，是否确认删除？',
		'删除提示',
		{
			confirmButtonText: '确定',
			cancelButtonText: '取消',
			type: 'warning',
		}
	).then(async () => {
		const ids = isMultipleDeletetFlag ? rows.map((item: RowType) => item.id) : [rows.id]
		const params = {id: ids, sys_name: SYS_NAME, service_name: mainParams.serviceName}
		const res = await serviceListDetailsDeleteRqs(params)
		if(res?.code === REQUEST_SUCCESS_NO) {
			ElMessage.success(res.msg)
			queryServiceListDetailFn(mainParams.serviceIndex)
		}
	}).catch(() => {
		ElMessage({
			type: 'info',
			message: '删除操作已取消',
		})
	})
}

// 启用/禁用开关的接口操作
// isMultipleSwitchFlag 是否批量操作
// isSwitchOnFlag 是否启用
const switchUpdateFn = async (params: SwitchUpdateFnParamsType, isSwitchOnFlag: boolean, tipTxt: string) => {
	const res = isSwitchOnFlag ? await serviceSwitchOnRqs(params) : await serviceSwitchOffRqs(params)
	if(res?.code === REQUEST_SUCCESS_NO) {
		ElMessage.success(tipTxt)
		// 更新页面
		queryServiceListDetailFn(mainParams.serviceIndex)
	}
}
// 启用/禁用开关，支持批量操作
const switchChangeFn = (rows: RowType | RowType[], title?: string, isSwitchOnFlag?: boolean) => {
	let tipTxt = '', isMultipleSwitchFlag = false
	if(Array.isArray(rows)) {
		tipTxt = title!
		isMultipleSwitchFlag = true
	} else {
		isSwitchOnFlag = rows.is_enable ? true : false
		tipTxt = rows.is_enable ? '启用' : '禁用'
	}
	ElMessageBox.confirm(
		`请确认是否要${tipTxt}`,
		`${tipTxt}提示`,
		{
			confirmButtonText: '确定',
			cancelButtonText: '取消',
			type: 'warning',
			// 点击区域外不关闭
			closeOnClickModal: false
		}
	).then(() => {
		const ids = isMultipleSwitchFlag ? rows.map((item: RowType) => item.id) : [rows.id]
		const params = {id: ids, sys_name: SYS_NAME, service_name: mainParams.serviceName}
		if(typeof isSwitchOnFlag === 'boolean') switchUpdateFn(params, isSwitchOnFlag, `${tipTxt}成功`)
	}).catch(() => {
		ElMessage.info(`${tipTxt}操作已取消`)
		// 更新页面
		queryServiceListDetailFn(mainParams.serviceIndex)
	})
}

// 翻页事件
const tableDataUpdateEventFn = () => {
	// 单独记录每个服务实例对应的分页状态
	mainParams.serviceList[mainParams.serviceIndex].currentPage = tableData.currentPage
	mainParams.serviceList[mainParams.serviceIndex].pageSize = tableData.pageSize

	// 更新页面数据
	queryServiceListDetailFn(mainParams.serviceIndex)
}

onMounted(() => {
	queryServiceListFn()

	// 批量删除, isMultipleDeletetFlag 是否批量删除操作
	$mitt.on('TABLE_MULTIPLE_DELETE_EVENT', rows => {
		const isMultipleDeletetFlag = true
		tableDataDeleteEventFn(rows, isMultipleDeletetFlag)
	})

	// 批量启用/禁用开关
	$mitt.on('TABLE_MULTIPLE_SWITCH_EVENT', (multipleParams: Events['TABLE_MULTIPLE_SWITCH_EVENT']) => {
		const {rows, title, isSwitchOnFlag} = multipleParams
		switchChangeFn(rows, title, isSwitchOnFlag)
	})
})

onBeforeUnmount(() => {
	$mitt.all.delete('TABLE_MULTIPLE_DELETE_EVENT')
	$mitt.all.delete('TABLE_MULTIPLE_SWITCH_EVENT')
})
</script>

<template>
	<ul class="service-bar list-inline child-mr-15 mb-20">
		<li 
			v-for="(item, index) in mainParams.serviceList" 
			:key="index" 
			:class="[`bg-${item.bgColor} ${mainParams.serviceIndex === index ? 'active bg-white' : ''}`]" 
		>
			<div 
				class="service-item" 
				:class="[`bg-${item.bgColor} ${mainParams.serviceIndex === index ? 'active' : ''}`]" 
				@click="queryServiceListDetailFn(index)" 
			>
				<div class="desc" :title="item.service_name" :alt="item.service_name">
					{{ item.service_name }}
				</div>
			</div>
		</li>
	</ul>

	<div class="operation-bar">
		<div>
			<el-button 
				type="primary" 
				:class="[`btn btn-${THEME_COLOR}`]" 
				v-preventReClick 
				v-auth 
				@click="tableDataAddEventFn" 
			>
				<el-icon><Plus /></el-icon>
				新增服务实例
			</el-button>
		</div>
		<MultipleOperation :multipleConfig="mainParams.multipleConfig" width="1.4rem" />
	</div>
mainParams.serviceList = {{ mainParams.serviceList }}
	<div class="service-table">
		<TableOperation 
			ref="tableRef" 
			:tableHeaderColumns="tableHeaderColumns" 
			v-model:tableData="tableData" 
			@TABLE_DATA_SELECT_EVENT="TABLE_DATA_SELECT_EVENT_FN(tableData.data)" 
			@TABLE_DATA_UPDATE_EVENT="tableDataUpdateEventFn" 
			@TABLE_DATA_VIEW_EVENT="tableDataViewEventFn" 
			@TABLE_DATA_EDIT_EVENT="tableDataEditEventFn" 
			@TABLE_DATA_DELETE_EVENT="tableDataDeleteEventFn" 
		>
			<template #deployTypeSlot="{row}">
				<span :title="row.deploy_type === 1
						?  '单机'
						: row.deploy_type === 2
							? '温备'
							: '热备'">
					{{ row.deploy_type === 1
						?  '单机'
						: row.deploy_type === 2
							? '温备'
							: '热备'
					}}
				</span>
			</template>
	
			<template #primarySlot="{row}">
				<template v-if="row.deploy_type === 1 || row.deploy_type === 2">
					<span 
						v-if="row.is_online" 
						class="table-icon-txt" 
						:class="[`${row.is_primary ? 'table-icon-t' : 'table-icon-f'}`]"
						:title="row.is_primary" 
					>
						{{ row.is_primary ? '主' : '备' }}
					</span>
					<span
						v-else 
						class="table-icon-txt" 
						:class="[`${row.is_primary ? 'table-icon-t' : 'table-icon-f'}`]" 
					>
						{{ row.is_primary ? '主' : '备' }}
					</span>
				</template>
				<span v-else :title="row.is_primary">
					{{ row.is_primary ? '主' : '备' }}
				</span>
			</template>
	
			<template #switchSlot="{row}">
				<el-switch 
					v-model="row.is_enable" 
					:style="[`--el-switch-on-color: ${SWITCH_ON_COLOR}; --el-switch-off-color: ${SWITCH_OFF_COLOR}`]" 
					active-text="on" 
					inactive-text="off" 
					:before-change="SWITCH_BEFORE_CHANGE_FN" 
					@change="switchChangeFn(row)" 
					inline-prompt 
				/>
			</template>
		</TableOperation>
	</div>

	<DialogRowView ref="dialogRowViewRef" />
	<DialogRowAddEdit ref="dialogAddEditRef" @CONFIRM_SUBMIT_EVENT="confirmSubmitEventFn" />
</template>

<style lang="scss" scoped>
.service-bar {
	display: -webkit-flex;
	display: flex;
	flex-wrap: wrap;

	li {
		margin-bottom: .1rem;
		padding: .04rem;
		border-radius: .1rem;
		border: .02rem solid transparent;
		&.active {
			border-color: $color-night;
		}
	}
	.service-item {
		position: relative;
		display: -webkit-flex;
		display: flex;
		flex-direction: column;
		justify-content: center;
		align-items: center;
		padding: .15rem;
		height: .7rem;
		border-radius: .1rem;
		font-size: .24rem;
		cursor: pointer;
		overflow: hidden;

		.desc {
			font-size: .16rem;
		}

		&.active {
			color: $color-night;
			.current-icon {
				display: block;
			}
		}
	}
}

.service-table {
	:deep(.table-icon-txt) {
		width: .24rem;
		height: .24rem;
		line-height: .24rem;
		text-align: center;
		font-size: .12rem;
		border-radius: 50%;
		color: $color-white;

		&.table-icon-t {
			background-image: linear-gradient(#90ea7e, #388a28);
		}
		&.table-icon-f {
			background-image: linear-gradient(#77b9fd, #2987e9);
		}
		&.table-icon-offline {
			background-image: linear-gradient(#f67070, #d34f4f);
		}
	}
}
</style>